/*
 * @Descripttion: 绘制动画实体
 * @version: 1.0.0
 * @Date: 2022-03-14 16:41:19
 * @LastEditTime: 2022-06-22 15:13:19
 */
import { CityFlagEnum, SideEnum } from "@@/enums/observation";
import {
  IStepEntityInfo,
  ITrackEntityInfo,
  ISideStep,
  IStep,
} from "@@/typings/observation";
import {
  Cartesian2,
  Cartesian3,
  Color,
  Entity,
  JulianDate,
  LabelStyle,
  TimeInterval,
  TimeIntervalCollection,
  Math as CesiumMath,
  TimeIntervalCollectionProperty,
  SampledPositionProperty,
  defined,
} from "cesium";
import moment from "moment";
import {
  CustomViewer,
  IAnimation,
  IAnimationGroup,
} from "../CustomCesium/CustomCesium";
import { simulationStateTuiyan } from "@@/store-tuiyan/modules";

interface IEntityInfo {
  id: number | string;
  name: string;
  image: string;
  side?: SideEnum | string;
  flag?: CityFlagEnum;
  positions: { time: JulianDate[]; data: Cartesian3[] };
  rotations: { time: JulianDate[]; data: number[] };
}

interface IEntities {
  [id: number]: IEntityInfo;
}

/// 根据态势创建动画
export default class ScenarioUtilTuiyan {
  /// 根据记录返回新的状态
  private static getNewPropertyTuiyan(
    positions: { time: JulianDate[]; data: Cartesian3[] },
    rotations: { time: JulianDate[]; data: number[] }
  ) {
    const length = rotations.data.length,
      position = new SampledPositionProperty(),
      rotation = new TimeIntervalCollectionProperty(),
      timeInterval = new TimeInterval({
        start: positions.time[1],
        stop: positions.time[length - 1],
      }),
      timeIntervalCollection = new TimeIntervalCollection();
    timeIntervalCollection.addInterval(timeInterval);

    /// 位置时间序列
    position.addSamples(positions.time, positions.data);
    /// 旋转时间序列
    for (let index = 0; index < length; index++) {
      const time = rotations.time[index],
        nextTime = rotations.time[index + 1],
        data = rotations.data[index];
      rotation.intervals.addInterval(
        new TimeInterval({
          start: time,
          stop: nextTime,
          data: nextTime ? data : 0,
        })
      );
    }

    return { position, rotation, timeIntervalCollection };
  }

  /// 创建实体
  private static createEntityTuiyan(
    entityInfo: IEntityInfo,
    availability?: TimeIntervalCollection
  ) {
    const {
      id,
      name,
      image,
      side,
      flag,
      positions,
      rotations,
    } = entityInfo,
    simulStore = simulationStateTuiyan();
    /// 动画步长为1
    let position: Cartesian3 | SampledPositionProperty =
        entityInfo.positions.data[0],
      rotation: number | TimeIntervalCollectionProperty =
        entityInfo.rotations.data[0];
    /// 动画步长超过1
    if (positions.data.length > 1) {
      position = new SampledPositionProperty();
      rotation = new TimeIntervalCollectionProperty();
      /// 位置时间序列
      position.addSamples(positions.time, positions.data);
      /// 旋转时间序列
      for (let index = 0; index < rotations.data.length; index++) {
        const time = rotations.time[index],
          nextTime = rotations.time[index + 1],
          data = rotations.data[index];
        rotation.intervals.addInterval(
          new TimeInterval({
            start: time,
            stop: nextTime,
            data: nextTime ? data : 0,
          })
        );
      }
    }
    const resourceEntity = new Entity({
      id: id + "",
      availability,
      position,
      billboard: {
        image: `/assets/scenario/images/${image}`,
        rotation,
      },
      label: {
        show: simulStore.isShowLabelTuiyan,
        text: name + "-" + id,
        scale: 0.4,
        fillColor:
          side == 1
            ? Color.RED
            : side == SideEnum.blue
            ? Color.STEELBLUE
            : Color.BLACK,
        outlineColor: Color.WHITE,
        outlineWidth: 1,
        style: LabelStyle.FILL_AND_OUTLINE,
        pixelOffset: new Cartesian2(0.0, 25.0),
      },
      properties: {
        id,
        side,
        flag,
        positions,
        rotations,
      },
    });
    return resourceEntity;
  }

  /// 添加实体信息
  private static addEntityInfoTuiyan(
    entities: IEntities,
    model: IStepEntityInfo,
    currentTime: JulianDate
  ) {
    const { m_id, m_EntityName, m_Position, m_Side, m_Heading, m_EntityType } =
        model,
      cartesian3 = Cartesian3.fromDegrees(
        m_Position?.longitude || 0,
        m_Position?.latitude || 0
      );
    if (!defined(cartesian3)) return;
    /// 已存在实体信息，则继续添加旋转、位置数据
    if (entities[m_id]) {
      const entity = entities[m_id];
      /// 旋转
      entity.rotations.time.push(currentTime);
      entity.rotations.data.push(CesiumMath.toRadians(-(m_Heading || 0)));
      /// 位置
      entity.positions.time.push(currentTime);
      entity.positions.data.push(cartesian3);
    }
    /// 添加新实体信息
    else {
      const image = `${m_Side == 1 ? "red/" : "blue/"}${m_EntityType?.m_kind}-${
          m_EntityType?.m_domain
        }-${m_EntityType?.m_category}.png`,
        rotations: { time: JulianDate[]; data: number[] } = {
          time: [],
          data: [],
        },
        positions: { time: JulianDate[]; data: Cartesian3[] } = {
          time: [],
          data: [],
        };
      /// 旋转
      rotations.time.push(currentTime);
      rotations.data.push(CesiumMath.toRadians(-(m_Heading || 0)));
      /// 位置
      positions.time.push(currentTime);
      positions.data.push(cartesian3);
      entities[m_id] = {
        id: m_id,
        name: m_EntityName,
        image,
        side: m_Side,
        positions,
        rotations,
      };
    }
  }

  /// 添加探测实体信息
  private static addTrackEntityInfoTuiyan(
    entities: IEntities,
    model: ITrackEntityInfo,
    currentTime: JulianDate
  ) {
    const { m_id, m_EntityName, m_Position, m_Side, m_Heading, m_EntityType } =
        model,
      cartesian3 = Cartesian3.fromDegrees(
        m_Position?.longitude || 0,
        m_Position?.latitude || 0
      );
    if (!defined(cartesian3)) return;
    /// 已存在实体信息，则继续添加旋转、位置数据
    if (entities[m_id]) {
      const entity = entities[m_id];
      /// 旋转
      entity.rotations.time.push(currentTime);
      entity.rotations.data.push(CesiumMath.toRadians(-(m_Heading || 0)));
      /// 位置
      entity.positions.time.push(currentTime);
      entity.positions.data.push(cartesian3);
    }
    /// 添加新实体信息
    else {
      const image = `${m_Side == 1 ? "red/" : "blue/"}${m_EntityType?.m_kind}-${
          m_EntityType?.m_domain
        }-${m_EntityType?.m_category}.png`,
        rotations: { time: JulianDate[]; data: number[] } = {
          time: [],
          data: [],
        },
        positions: { time: JulianDate[]; data: Cartesian3[] } = {
          time: [],
          data: [],
        };
      /// 旋转
      rotations.time.push(currentTime);
      rotations.data.push(CesiumMath.toRadians(-(m_Heading || 0)));
      /// 位置
      positions.time.push(currentTime);
      positions.data.push(cartesian3);
      entities[m_id] = {
        id: m_id,
        name: m_EntityName,
        image,
        side: m_Side,
        positions,
        rotations,
      };
    }
  }

  /// 创建初始动画
  static createInitAnimationsBySideStepTuiyan(
    customViewer: CustomViewer,
    step: ISideStep,
    visualAngel: string
  ) {
    const entities: IEntities = {},
      animations: IAnimation[] = [],
      /// 初始时间戳
      startStampTime = step.simul_time * 1000,
      startJulianTime = JulianDate.fromDate(moment(startStampTime).toDate()),
      endJulianTime = JulianDate.addMinutes(
        startJulianTime,
        1,
        new JulianDate()
      );

    // 筛选实体信息
    step.obj_list && step.obj_list.forEach((model) => {
      if (Object.prototype.hasOwnProperty.call(entities, model.m_id)) {
        return
      }
      this.addEntityInfoTuiyan(entities, model, startJulianTime);
    });

    step.detect_list?.forEach((model) => {
      if (Object.prototype.hasOwnProperty.call(entities, model.m_id)) {
        return
      }
      model.m_Side = (visualAngel === 'red' ? SideEnum.blue : visualAngel === 'blue' ? SideEnum.red : model.m_Side)
      this.addTrackEntityInfoTuiyan(entities, model, startJulianTime);
    });

    /// 根据实体创建动画
    for (const key in entities) {
      if (Object.prototype.hasOwnProperty.call(entities, key)) {
        const entityInfo = entities[key],
          entity = this.createEntityTuiyan(entityInfo),
          animation = customViewer.animationManager?.createAnimation(entity);

        /// 剔除无效数据
        animation?.entity.id != `undefined` &&
          animation &&
          animations.push(animation);
      }
    }
    return {
      animations,
      period: { startTime: startJulianTime, endTime: endJulianTime },
    };
  }

  /// 更新动画
  static updateAnimationsBySideStepTuiyan(
    customViewer: CustomViewer,
    animationGroup: IAnimationGroup,
    step: ISideStep,
    visualAngel: string,
    isStart = false
  ) {
    /// 当前时间戳
    const currentStampTime = step.simul_time * 1000,
      currentJulianTime = JulianDate.fromDate(
        moment(currentStampTime).toDate()
      );

    animationGroup.removeAll();
    /// 遍历新的实体集合
    step.obj_list && step.obj_list.forEach(
      ({ m_id, m_EntityName, m_Heading, m_Position, m_Side, m_EntityType }) => {
        const entity = animationGroup.datasource.entities.getById(m_id + ""),
          cartesian3 = Cartesian3.fromDegrees(
            m_Position?.longitude || 0,
            m_Position?.latitude || 0
          ),
          rotation = CesiumMath.toRadians(-(m_Heading || 0));
        if (defined(cartesian3))
          if (entity) {
            const properties = entity.properties?.getValue(currentJulianTime),
              positions = properties.positions,
              rotations = properties.rotations;
            if (positions) {
              positions.time.push(currentJulianTime);
              positions.data.push(cartesian3);
              rotations.time.push(currentJulianTime);
              rotations.data.push(rotation);

              const newState = this.getNewPropertyTuiyan(positions, rotations);
              entity.position = newState.position;
              entity.billboard &&
                (entity.billboard.rotation = newState.rotation);
            }
          } else {
            const image = `${m_Side == 1 ? "red/" : "blue/"}${
                m_EntityType?.m_kind
              }-${m_EntityType?.m_domain}-${m_EntityType?.m_category}.png`,
              newEntity = this.createEntityTuiyan(
                {
                  id: m_id,
                  name: m_EntityName,
                  side: m_Side,
                  image,
                  positions: { time: [currentJulianTime], data: [cartesian3] },
                  rotations: { time: [currentJulianTime], data: [rotation] },
                }
              ),
              animation =
                customViewer.animationManager?.createAnimation(newEntity);

            if (animation)
              animation?.id != `undefined` && animationGroup.add(animation);
          }
      }
    );

    /// 添加探测到的实体
    step.detect_list?.forEach(
      ({ m_id, m_EntityName, m_Heading, m_Position, m_Side, m_EntityType }) => {
        const entity = animationGroup.datasource.entities.getById(m_id + ""),
          cartesian3 = Cartesian3.fromDegrees(
            m_Position?.longitude || 0,
            m_Position?.latitude || 0
          ),
          rotation = CesiumMath.toRadians(-(m_Heading || 0));
        if (entity) {
          const properties = entity.properties?.getValue(currentJulianTime),
            positions = properties.positions,
            rotations = properties.rotations;
          if (positions) {
            positions.time.push(currentJulianTime);
            positions.data.push(cartesian3);
            rotations.time.push(currentJulianTime);
            rotations.data.push(rotation);

            const newState = this.getNewPropertyTuiyan(positions, rotations);
            entity.position = newState.position;
            entity.billboard && (entity.billboard.rotation = newState.rotation);
          }
        } else {
          m_Side = (visualAngel === 'red' ? SideEnum.blue : visualAngel === 'blue' ? SideEnum.red : m_Side)
          const image = `${m_Side == 1 ? "red/" : "blue/"}${
              m_EntityType?.m_kind
            }-${m_EntityType?.m_domain}-${m_EntityType?.m_category}.png`,
            newEntity = this.createEntityTuiyan(
              {
                id: m_id,
                name: m_EntityName,
                side: m_Side,
                image,
                positions: { time: [currentJulianTime], data: [cartesian3] },
                rotations: { time: [currentJulianTime], data: [rotation] },
              }
            ),
            animation =
              customViewer.animationManager?.createAnimation(newEntity);

          /// 剔除无效数据
          if (animation)
            animation.id != `undefined` && animationGroup.add(animation);
        }
      }
    );

    /// 更新动画时间
    if (
      JulianDate.greaterThan(
        currentJulianTime,
        animationGroup.period.endTime
      ) ||
      isStart
    ) {
      animationGroup.updatePeriod(
        undefined,
        JulianDate.addSeconds(currentJulianTime, 30, new JulianDate())
      );
    }

    if (
      JulianDate.lessThan(currentJulianTime, animationGroup.period.startTime) ||
      isStart
    ) {
      animationGroup.updatePeriod(currentJulianTime);
    }

    /// 更新当前时间
    customViewer.timeManager?.updateCurrentTime(currentJulianTime);
  }
}
